#include "Precompile.h"
#include "GeneralSettings.h"

namespace Core{
	std::map<std::string,GeneralSettings::SettingCategory> GeneralSettings::m_settingsMap;
	std::string GeneralSettings::m_dataPath;

	GeneralSettings::GeneralSettings(){
	
	}

	void GeneralSettings::loadConfigFile(std::string &filename){
		std::ifstream file(filename);

		// Parse config file
		char line[256];
		std::string l;
		SettingCategory* category;

		while(!file.eof()){
			file.getline(line,256);
			l = line;
			if(l.size() > 0){
				if(l[0] == '['){
					category = &m_settingsMap[l];
				}
				else if(l[0] == '{'){
					getCategory(category,file,line);
				}
			}
		}

		file.close();

		m_dataPath = getSettingValue(std::string("[Data Paths]"),std::string("ResourcePath"));
		if(m_dataPath.at(0) == '"'){
			m_dataPath = m_dataPath.substr(1,m_dataPath.size()-2);
		}
	}

	const std::pair<unsigned int,unsigned int>& GeneralSettings::getResolution(){
		static std::pair<unsigned int,unsigned int> resolution(0,0);
		if(resolution.first > 0)
			return resolution;

		// Get resolution from map
		std::string& res = getSettingValue(std::string("[Video Settings]"),std::string("Resolution"));

		resolution.first = Utility::StringConverter::parse<unsigned int>(res.substr(0,res.find_first_of('x')));
		resolution.second = Utility::StringConverter::parse<unsigned int>(res.substr(res.find_first_of('x')+1,res.size()));
		return resolution;
	}

	const unsigned int GeneralSettings::getMultisampleCount(){
		static unsigned int multisampleCount = 0;
		if(multisampleCount != 0)
			return multisampleCount;

		// Get multisample from map
		std::string& res = getSettingValue(std::string("[Video Settings]"),std::string("Multisampling"));

		multisampleCount = Utility::StringConverter::parse<unsigned int>(res);
		return multisampleCount;
	}

	bool GeneralSettings::getFullScreen(){
		static std::string fullscreen;
		if(!fullscreen.empty())
			return Utility::StringConverter::parse<bool>(fullscreen);

		// Get multisample from map
		std::string& res = getSettingValue(std::string("[Video Settings]"),std::string("FullScreen"));

		fullscreen = res;
		return Utility::StringConverter::parse<bool>(fullscreen);
	}

	std::string GeneralSettings::findFilePath(std::string &filename, std::string subDir){
		std::string file = filename,
					subDirectory = subDir;
		if(file.find('/') != std::string::npos || file.find('\\') != std::string::npos){
			if(file.find('/') != std::string::npos){
				subDirectory = file.substr(0,file.find_last_of('/')+1);
				file = file.substr(file.find_last_of('/')+1,file.size());
			}
			else{
				subDirectory = file.substr(0,file.find_last_of('\\')+1);
				file = file.substr(file.find_last_of('\\')+1,file.size());
			}
		}

		static std::string basePath = "";
		if(basePath.size() == 0){
			std::string& ref = getSettingValue(std::string("[Data Paths]"),std::string("ResourcePath"));
			basePath = ref.substr(1,ref.size()-2);
			if(subDirectory.find(basePath) != std::string::npos)
				basePath = "";
		}

		std::string result = "";
		std::string filePath = basePath;
		filePath += subDirectory+"*.*";
		
		// Search for file in data path
		struct _finddatai64_t data;
		long h = _findfirsti64(filePath.c_str(),&data);
		if(h >= 0){
			do{
				if(data.attrib == _A_SUBDIR){
					// subfolder
					if(strcmp(data.name,".") != 0 && strcmp(data.name,"..") != 0){
						result = findFilePath(file,subDirectory+data.name+"/");
						if(result.size() > 0)
							break;
					}
				}
				else{
					// file
					if(strcmp(data.name,file.c_str()) == 0){
						// File found!
						result = basePath+subDirectory+data.name;
						break;
					}
				}
			}while(_findnexti64(h,&data) == 0);
			_findclose(h);
		}
		else{
			LOG_ERROR("Unable to find " +file+ " in the data folder set in the config file.");
			assert(0);
		}

		return result;
	}

	std::vector<std::string> GeneralSettings::getFilesInFolder(std::string &folder){
		std::vector<std::string> files;

		static std::string basePath = "";
		if(basePath.size() == 0){
			std::string& ref = getSettingValue(std::string("[Data Paths]"),std::string("ResourcePath"));
			basePath = ref.substr(1,ref.size()-2);
		}

		std::string folderPath = basePath+folder+"*.*";

		struct _finddatai64_t data;
		long h = _findfirsti64(folderPath.c_str(),&data);
		if(h >= 0){
			do{
				if(data.attrib == _A_SUBDIR){
					// subfolder
					continue;
				}
				else{
					// File found!
					files.push_back(basePath+folder+data.name);
				}
			}while(_findnexti64(h,&data) == 0);
			_findclose(h);	
		}

		return files;
	}

	void GeneralSettings::applyNewSettings(){
		
	}

	void GeneralSettings::getCategory(SettingCategory* category, std::ifstream &file, char* readBuffer){
		std::string line;
		int equalPos = 0;

		file.getline(readBuffer,256);
		line = readBuffer;
		do{
			if((equalPos = line.find_first_of('=')) != std::string::npos)
				(*category)[line.substr(0,equalPos)] = line.substr(equalPos+1,line.size());

			file.getline(readBuffer,256);
			line = readBuffer;
		}while(line[0] != '}' && !file.eof());
	}

	std::string GeneralSettings::getSettingValue(std::string category, std::string post){
		std::map<std::string,SettingCategory>::iterator itr = m_settingsMap.find(category);
		if(itr == m_settingsMap.end()){
			LOG_ERROR("Unable to find "+category+" category in config file.");
			assert(0);
			return std::string("");
		}

		SettingCategory::iterator it = itr->second.find(post);
		if(it == itr->second.end()){
			LOG_ERROR("Unable to find "+post+" post in video settings category of config file.");
			assert(0);
			return std::string("");
		}

		return it->second;
	}
}